package com.tsu.mall.common.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.tsu.mall.common.VO.LayuiTableVO;
import com.tsu.mall.common.VO.PayInfoVO;
import com.tsu.mall.common.VO.PersonalVO;
import com.tsu.mall.common.VO.ResultVO;
import com.tsu.mall.common.entity.*;
import com.tsu.mall.common.mapper.BillAddressMapper;
import com.tsu.mall.common.mapper.BillDetailMapper;
import com.tsu.mall.common.mapper.BillMapper;
import com.tsu.mall.common.service.IBillService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tsu.mall.common.service.IPayService;
import com.tsu.mall.common.util.RequestUtil;
import com.tsu.mall.common.util.SnowflakeIdGeneratorUtil;
import org.apache.activemq.ScheduledMessage;
import org.apache.activemq.command.ActiveMQQueue;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.jms.JmsProperties;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.jms.annotation.EnableJms;
import org.springframework.jms.core.JmsMessagingTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.jms.*;
import java.io.Serializable;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author tttttt
 * @since 2023-03-30
 */
@Service
@EnableJms//支持定时任务调度
public class BillServiceImpl extends ServiceImpl<BillMapper, Bill> implements IBillService {

    @Autowired
    private BillMapper billMapper;
    @Autowired
    private RedisTemplate<String,Object> redisTemplate;
    @Autowired
    private BillDetailMapper billDetailMapper;
    @Autowired
    private BillAddressMapper billAddressMapper;

    @Autowired
    private IPayService IpayService;


    @Autowired
    private JmsMessagingTemplate jmsMessagingTemplate;
    @Override
    public ResultVO list(Integer page, Integer limit, String accountNumber, String code,String billStatus) {
        PageHelper.startPage(page,limit);
        ResultVO vo=new ResultVO();
        List<Bill> list=baseMapper.doselectList(accountNumber,code,billStatus);
        vo.setData(list);
        vo.setCount(new PageInfo<>(list).getTotal());
        return vo;
    }

    @Override
    public LayuiTableVO doUpdateStatus(Integer id) {
        LayuiTableVO vo = new LayuiTableVO();
        baseMapper.doUpdateStatus(id);
        vo.setMsg("发货成功！");
        return vo;
    }

    //保存订单
    @Override
    @Transactional
    public PayInfoVO saveBill(String ids, String remark, Integer memberAddressId) {
        //获取当前登录用户
        Member m= RequestUtil.getCurrent();

        //计算商品总价
        BigDecimal sumPrice = new BigDecimal(0);
        for (String cartId:ids.split(",")){
           Cart cart=billMapper.selectByCartId(Integer.parseInt(cartId));//查询当前会员购物车数据
            Wares wares=billMapper.doSelectById(cart.getWaresId());//商品数据
            sumPrice=sumPrice.add(wares.getPrice().multiply(BigDecimal.valueOf(cart.getAmount()))).add(new BigDecimal(9));
        }

        //保存订单数据
        Bill bill=new Bill();
        bill.setCreateTime(LocalDateTime.now());
        bill.setMemberId(m.getId());
        bill.setStatus("待支付");
        bill.setPrice(sumPrice);
        bill.setRemark(remark);
        bill.setPayType("alipay");
        //使用雪花算法订单号
        long billCode=SnowflakeIdGeneratorUtil.nextId();
        bill.setCode(String.valueOf(billCode));
        //设置流水号
        String pre="LTMALL"+new SimpleDateFormat("yyMM").format(new Date());
        bill.setSerialNumber(GetNextNo(pre));
        baseMapper.insert(bill); //保存订单

        //订单详情表
        for(String cartId:ids.split(",")){
            BillDetail detail=new BillDetail();
            Cart cart=billMapper.selectByCartId(Integer.parseInt(cartId));//查询当前会员购物车数据
            detail.setWaresId(cart.getWaresId());
            detail.setBillId(bill.getId());
            detail.setAmount(cart.getAmount());
            detail.setMemberWaresColor(cart.getMemberWaresColor());
            detail.setMemberWaresVersion(cart.getMemberWaresVersion());
            detail.setMemberWaresSize(cart.getMemberWaresSize());
            detail.setStatus(bill.getStatus());
            billDetailMapper.insert(detail);
            //删除购物车中的数据
            billMapper.deleteByCartId(Integer.parseInt(cartId));
        }

        //订单地址表
        BillAddress billAddress=new BillAddress();
        billAddress.setBillId(bill.getId());
        //在会员地址表查询该订单用的地址详情
        MemberAddress address=billMapper.selectByAddressId(memberAddressId);
        billAddress.setProvince(address.getProvince());
        billAddress.setCity(address.getCity());
        billAddress.setArea(address.getArea());
        billAddress.setAddress(address.getAddress());
        billAddress.setName(address.getName());
        billAddress.setPhone(address.getPhone());
        billAddressMapper.insert(billAddress);
        //推送消息队列 1分钟后取消订单
        delaySend(new ActiveMQQueue("bill.save"),bill.getId(),60000L);
        //调用service对接支付 该订单对接支付宝 生成支付二维码
        String qrcode=IpayService.createPayBill(bill);
        PayInfoVO  payInfo=new PayInfoVO();
        payInfo.setQrcode(qrcode);
        payInfo.setCode(bill.getCode());
        return payInfo;
    }


    private <T extends Serializable> void delaySend(Destination queue, T data, Long time) {
        Connection conn = null;
        Session session = null;
        MessageProducer producer = null;

        ConnectionFactory connectionFactory = jmsMessagingTemplate.getConnectionFactory();
        try {
            conn = connectionFactory.createConnection();
            conn.start();
            session = conn.createSession(Boolean.TRUE, Session.AUTO_ACKNOWLEDGE);
            //创建一个生产者
            producer = session.createProducer(queue);
            producer.setDeliveryMode(JmsProperties.DeliveryMode.PERSISTENT.getValue());
            ObjectMessage message = session.createObjectMessage(data);
            message.setLongProperty(ScheduledMessage.AMQ_SCHEDULED_DELAY, time);
            producer.send(message);
            session.commit();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (producer != null) {
                    producer.close();
                }
                if (session != null) {
                    session.close();
                }
                if (conn != null) {
                    conn.close();
                }
            } catch (Exception ignored) {

            }
        }
    }


    @Override
    public List<Bill> doList(Integer id) {
       return  baseMapper.doList(id);
    }

    @Override
    public Bill selectById(Integer billId) {
        return baseMapper.selectById(billId);
    }

    @Override
    public void deleteById(Integer billId) {
        //删除订单数据
        baseMapper.deleteById(billId);
        //删除订单详情数据
        baseMapper.deleteBillDetailById(billId);
        //删除订单地址表
        baseMapper.deleteBillAddressById(billId);
    }

    @Override
    public List<Bill> doListByStatus(Integer id, String status) {
        return baseMapper.selectByStatus(status);
    }

    @Override
    public PersonalVO doSelectByStatus(Integer memberId) {
        return baseMapper.doSelectByStatus(memberId);
    }

    @Override
    public Integer doSelectByCode(String billCode) {
        return baseMapper.doSelectByCode(billCode);
    }

    @Override
    public Bill doSelectByid(Integer id) {
        return baseMapper.doSelectBillById(id);
    }


    //订单超时自动取消
    @Override
    public void updateStatusById(Integer id) {
        baseMapper.updateBillStatusById(id);
        baseMapper.updateBillDetailStatusById(id);
    }

    @Override
    public List<Bill> doList(String accountNumber, String code, String billStatus) {
        return  baseMapper.doselectList(accountNumber,code,billStatus);
    }

    //获取一个前缀，返回下一个订单号
    private synchronized String GetNextNo(String pre){
        //获取此前缀的最大值
        Object obj=redisTemplate.opsForValue().get(pre);
        int nextNo;
        if(obj==null){
            String maxCode=baseMapper.selectMaxCode(pre);
            if(maxCode==null){
                nextNo=1;
            }else{
                String no=maxCode.substring(pre.length());
                nextNo=Integer.parseInt(no)+1;
            }
            redisTemplate.opsForValue().set(pre, nextNo);
        }else{
            nextNo=(int)obj;
            redisTemplate.opsForValue().set(pre, nextNo+1);
        }
        return pre+new DecimalFormat("0000").format(nextNo);
    }

}
